#!/usr/bin/python
# -*- coding: utf-8 -*-

# This file is part of Cockpit.
#
# Copyright (C) 2015 Red Hat, Inc.
#
# Cockpit is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Cockpit is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Cockpit; If not, see <http://www.gnu.org/licenses/>.

import parent
import unittest

from testlib import *
import kubelib

@skipImage("No kubernetes packaged", "debian-8", "debian-testing", "ubuntu-1604")
@skipImage("No cockpit-kubernetes packaged", "continuous-atomic", "fedora-atomic", "rhel-atomic")
class TestKubernetes(kubelib.KubernetesCase, kubelib.KubernetesCommonTests):

    def setUp(self):
        kubelib.KubernetesCase.setUp(self)
        m = self.machine

        self.start_kubernetes()

        m.upload(["verify/files/mock-k8s-tiny-app.json"], "/tmp")
        self.wait_api_server()

@skipImage("No kubernetes packaged", "debian-8", "debian-testing", "ubuntu-1604")
@skipImage("No cockpit-kubernetes packaged", "continuous-atomic", "fedora-atomic", "rhel-atomic")
class TestConnection(kubelib.KubernetesCase):
    def testConnect(self):
        m = self.machine
        b = self.browser

        # Connect without starting a kube server
        self.login_and_go("/kubernetes")
        b.wait_present(".curtains-ct")
        b.wait_visible(".curtains-ct")
        b.wait_in_text(".curtains-ct", "Couldn't connect to server")
        b.wait_in_text(".curtains-ct", "Couldn't find running API server")
        self.assertIn("Reconnect", b.text("#kubernetes-reconnect"))

        # Start a kube-apiserver with a 'wrong' http port, forcing use of https
        m.execute("echo 'KUBE_API_PORT=\"--port=1111\"' >> /etc/kubernetes/apiserver")
        m.execute("sed -i s/8080/1111/g /etc/kubernetes/*")
        self.start_kubernetes()
        self.wait_api_server(port=6443, scheme='https')

        # Setup the kube stuff in the right place
        m.upload(["verify/files/mock-kube-config-basic.json"], "/tmp")
        m.execute("mkdir -p /home/admin/.kube/ && mv /tmp/mock-kube-config-basic.json /home/admin/.kube/config")

        # Click the Reconnect button
        b.click("#kubernetes-reconnect")
        b.wait_present("#node-list")
        b.wait_in_text("#node-list", "127.0.0.1")
        b.logout()

        # Check that this failed as a double check
        output = m.execute("curl -sS http://localhost:8080/api 2>&1 || true")
        self.assertIn("Connection refused", output)

        # Check that this failed as a double check
        output = m.execute("curl -k -sS https://localhost:6443/api 2>&1 || true")
        self.assertIn("Unauthorized", output)

        m.execute("rm -r /home/admin/.kube")
        self.login_and_go("/kubernetes")

        b.wait_present(".curtains-ct")
        b.wait_present("#kubernetes-connection-tb")
        b.click("#kubernetes-connection-tb")

        b.wait_present("modal-dialog")
        b.wait_in_text("div.modal-footer div.dialog-error", "Connection Error: Unauthorized")
        b.wait_present("#kubernetes-address")
        b.wait_present("#kubernetes-cluster")
        b.wait_not_present("#kubernetes-user")

        b.wait_present("#kubernetes-cluster ul.dropdown-menu")
        b.wait_in_text("#kubernetes-cluster button", "Add New Cluster")

        b.click("#kubernetes-requires-auth")
        b.wait_present("#kubernetes-user")
        b.wait_present("#kubernetes-username")
        b.wait_in_text("#kubernetes-user button", "Add New User")
        b.set_val("#kubernetes-address", "")
        b.click("modal-dialog div.modal-footer button.btn-primary")
        b.wait_present("#kubernetes-address + div.dialog-error")
        b.wait_present("#kubernetes-username + div.dialog-error")

        b.set_val("#kubernetes-address", "https://127.0.0.1:6443")
        b.set_val("#kubernetes-username", "bad")
        b.set_val("#kubernetes-password", "password")

        b.click("modal-dialog div.modal-footer button.btn-primary")
        b.wait_present("modal-dialog input[value='pem']")
        b.wait_present("modal-dialog input[value='skip']")
        b.wait_in_text("modal-dialog pre", "Certificate:")
        b.click("modal-dialog input[value='pem']")
        b.click("modal-dialog div.modal-footer button.btn-primary")

        b.wait_present("#kubernetes-address")
        b.wait_present("#kubernetes-user")
        b.wait_in_text("div.modal-footer div.dialog-error", "Connection Error: Unauthorized")

        # Data not saved
        b.wait_in_text("#kubernetes-cluster button", "Add New Cluster")
        b.wait_in_text("#kubernetes-user button", "Add New User")

        # Form is
        b.wait_val("#kubernetes-address", "https://127.0.0.1:6443")
        b.wait_present("#kubernetes-requires-auth:checked")
        b.wait_val("#kubernetes-username", "bad")

        b.set_val("#kubernetes-username", "admin")
        b.set_val("#kubernetes-password", "fubar")
        b.click("modal-dialog div.modal-footer button.btn-primary")
        b.wait_not_present("modal-dialog")

        b.wait_present("#node-list")
        b.wait_in_text("#node-list", "127.0.0.1")

        b.wait_not_present("#kubernetes-change-connection")

        # Temp certificate isn't saved
        b.reload()
        b.enter_page("/kubernetes")
        b.wait_present(".curtains-ct")
        b.wait_present("#kubernetes-connection-tb")
        b.click("#kubernetes-connection-tb")

        b.wait_present("modal-dialog input[value='pem']")
        b.wait_present("modal-dialog input[value='skip']")
        b.click("modal-dialog input[value='skip']")
        b.click("modal-dialog div.modal-footer button.btn-primary")
        b.wait_not_present("modal-dialog")

        b.wait_present("#node-list")
        b.wait_in_text("#node-list", "127.0.0.1")

        # Reload works
        b.reload()
        b.enter_page("/kubernetes")
        b.wait_present("#node-list")
        b.wait_in_text("#node-list", "127.0.0.1")

        # Changing works
        b.wait_present("#kubernetes-change-connection")
        b.click("#kubernetes-change-connection")
        b.wait_present("modal-dialog")
        b.wait_present("#kubernetes-cluster")
        b.wait_present("#kubernetes-user")

        b.wait_in_text("#kubernetes-cluster button", "127-0-0-1:6443")
        b.wait_in_text("#kubernetes-user button", "admin/127-0-0-1:6443")

        b.wait_val("#kubernetes-address", "https://127.0.0.1:6443")
        b.wait_present("#kubernetes-requires-auth:checked")
        b.wait_val("#kubernetes-username", "admin")
        b.wait_present("#kubernetes-skip-verify:checked")

        b.set_val("#kubernetes-address", "https://localhost:6443")
        b.set_val("#kubernetes-username", "scruffy")
        b.set_val("#kubernetes-password", "scruffy")
        b.click("modal-dialog div.modal-footer button.btn-primary")
        b.wait_not_present("modal-dialog")

        # Changes took and dropdowns work
        b.wait_present("#kubernetes-change-connection")
        b.click("#kubernetes-change-connection")
        b.wait_present("modal-dialog")
        b.wait_present("#kubernetes-cluster")
        b.wait_present("#kubernetes-user")

        b.wait_in_text("#kubernetes-cluster button", "127-0-0-1:6443")
        b.click("#kubernetes-cluster button")
        b.click("#kubernetes-cluster ul li:last-child a")
        b.wait_in_text("#kubernetes-cluster button", "Add New Cluster")
        b.wait_val("#kubernetes-address", "")
        b.wait_present("#kubernetes-skip-verify:not(:checked)")

        b.click("#kubernetes-cluster button")
        b.click("#kubernetes-cluster ul li:first-child a")
        b.wait_in_text("#kubernetes-cluster button", "127-0-0-1:6443")
        b.wait_val("#kubernetes-address", "https://localhost:6443")
        b.wait_present("#kubernetes-requires-auth:checked")
        b.wait_present("#kubernetes-skip-verify:checked")

        b.wait_in_text("#kubernetes-user button", "admin/127-0-0-1:6443")
        b.wait_val("#kubernetes-username", "scruffy")
        b.click("#kubernetes-user button")
        b.click("#kubernetes-user ul li:last-child a")
        b.wait_in_text("#kubernetes-user button", "Add New User")
        b.wait_val("#kubernetes-username", "")
        b.wait_val("#kubernetes-password", "")
        b.click("#kubernetes-user button")
        b.click("#kubernetes-user ul li:first-child a")
        b.wait_in_text("#kubernetes-user button", "admin/127-0-0-1:6443")
        b.wait_val("#kubernetes-username", "scruffy")
        b.wait_val("#kubernetes-password", "scruffy")

        b.click("modal-dialog div.modal-footer button.btn-cancel")
        b.wait_not_present("modal-dialog")

        b.wait_present("#node-list")
        b.wait_in_text("#node-list", "127.0.0.1")

        self.allow_journal_messages(".*: couldn't connect: Connection refused",
                                    ".*: Unacceptable TLS certificate.*",
                                    ".*: Connection reset by peer.*",
                                    "connection unexpectedly closed by peer",
                                    ".*: Error sending data: Broken pipe.*")

@skipImage("No kubernetes packaged", "debian-8", "debian-testing", "ubuntu-1604")
@unittest.skipIf(True, "Nulecule deploys temporarily removed.")
class TestNulecule(kubelib.KubernetesCase):
    def setUp(self):
        kubelib.KubernetesCase.setUp(self)

        self.start_kubernetes()
        self.wait_api_server()

    def testDeployDialog(self):
        b = self.browser
        m = self.machine

        self.login_and_go("/kubernetes")
        b.wait_present("#node-list")
        b.wait_in_text("#node-list", "127.0.0.1")

        # 1)check atomic version
        output = m.execute("atomic -v 2>&1")
        self.assertTrue(float(output) >= 1.1)

        # 2) fail  invalid image
        b.click("#deploy-app")
        b.wait_popup("deploy-app-dialog")
        b.set_val("#deploy-app-type", "nulecule")
        b.set_val("#deploy-app-nulecule-image", "submod/helloapache1")
        b.set_val("#deploy-app-namespace", "mynamespace")
        b.dialog_complete("#deploy-app-dialog", result="fail")
        b.dialog_cancel("#deploy-app-dialog")

        # 3) pass when valid image
        b.click("#deploy-app")
        b.wait_popup("deploy-app-dialog")
        b.set_val("#deploy-app-type", "nulecule")
        b.set_val("#deploy-app-nulecule-image", "submod/helloapache:0.1.11")
        b.set_val("#deploy-app-namespace", "mynamespace")
        b.click("#deploy-app-start")
        self.allow_journal_messages('Could not find any image matching "submod/helloapache:0.1.11".')
        b.wait_not_attr("#deploy-app-start", "disabled", "disabled")
        b.dialog_cancel("#deploy-app-dialog")

        # 4) fail when atomic is not installed
        m.needs_writable_usr()
        m.execute("rm /usr/bin/atomic")
        b.click("#deploy-app")
        b.wait_popup("deploy-app-dialog")
        b.set_val("#deploy-app-type", "nulecule")
        b.set_val("#deploy-app-nulecule-image", "submod/helloapache")
        b.set_val("#deploy-app-namespace", "mynamespace")
        b.dialog_complete("#deploy-app-dialog", result="fail")
        b.dialog_cancel("#deploy-app-dialog")

if __name__ == '__main__':
    test_main()
